#define coreAssertCudaError(error, message, body) if (cudaSuccess != error) { printf("E."message": %s.\n", cudaGetErrorString(error)); body; }
#define coreAssertCuResult(cuResult, message, body) if (CUDA_SUCCESS != cuResult) { printf("E."message":\n"); body; }

typedef struct AssertInfo_t
{
	unsigned int code;
	unsigned int code2;
} AssertInfo;

//cudaError_t error = cudaMemcpyFromSymbol(&lastAssert, "s_lastAssert", sizeof(lastAssert), 0, cudaMemcpyDeviceToHost);
void inline coreAssertCtor(AssertInfo** d_assertInfo, AssertInfo* assertInfo) { memset(assertInfo, 0, sizeof(AssertInfo)); cudaMalloc(d_assertInfo, sizeof(AssertInfo)); }
void inline coreAssertDispose(AssertInfo* d_assertInfo, AssertInfo* assertInfo) { cudaMemcpy(assertInfo, d_assertInfo, sizeof(AssertInfo), cudaMemcpyDeviceToHost); cudaFree(d_assertInfo); d_assertInfo = 0; }
void inline coreAssertDispose(AssertInfo* d_assertInfo) { cudaFree(d_assertInfo); d_assertInfo = 0; }

void inline coreCudaSetDevice(int deviceId)
{
	// get the number of non-emulation devices detected
	int devices = 0;
	cudaGetDeviceCount(&devices);
	if (deviceId > devices)
	{
		printf("deviceId >=  devices ... exiting\n");
		exit(1);
	}
	cudaDeviceProp deviceProp;
	cudaGetDeviceProperties(&deviceProp, deviceId);
	printf("device major.minor: %d.%d\n", deviceProp.major, deviceProp.minor);
	if (deviceProp.major > 999)
	{
		printf("warning, CUDA Device Emulation (CPU) detected, exiting\n");
		exit(1);
	}
	// choose a cuda device for kernel execution
	cudaError_t error = cudaSetDevice(deviceId);
	if (error == cudaErrorInvalidDevice)
		perror("cudaSetDevice returned cudaErrorInvalidDevice");
	else
	{
		// double check that device was properly selected
		int currentDeviceId;
		cudaGetDevice(&currentDeviceId);
		if (deviceId > currentDeviceId)
		{
			printf("not set to requested device, exiting\n");
			exit(1);
		}
	}
}
